<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>

    <style>
        canvas {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
        }
    </style>

    <script>
        /**
     * 3D Software ocean effect with Canvas2D
     * You can change properties under comment "Effect properties"
     */

        // Init Context
        let c = document.createElement('canvas').getContext('2d')
        let postctx = document.body.appendChild(document.createElement('canvas')).getContext('2d')
        let canvas = c.canvas
        let vertices = []

        // Effect Properties
        let vertexCount = 7000
        let vertexSize = 3
        let oceanWidth = 204
        let oceanHeight = -80
        let gridSize = 32;
        let waveSize = 16;
        let perspective = 100;

        // Common variables
        let depth = (vertexCount / oceanWidth * gridSize)
        let frame = 0
        let { sin, cos, tan, PI } = Math

        // Render loop
        let loop = () => {
            let rad = sin(frame / 100) * PI / 20
            let rad2 = sin(frame / 50) * PI / 10
            frame++
            if (postctx.canvas.width !== postctx.canvas.offsetWidth || postctx.canvas.height !== postctx.canvas.offsetHeight) {
                postctx.canvas.width = canvas.width = postctx.canvas.offsetWidth
                postctx.canvas.height = canvas.height = postctx.canvas.offsetHeight
            }


            c.fillStyle = `hsl(200deg, 100%, 2%)`
            c.fillRect(0, 0, canvas.width, canvas.height)
            c.save()
            c.translate(canvas.width / 2, canvas.height / 2)

            c.beginPath()
            vertices.forEach((vertex, i) => {
                let ni = i + oceanWidth
                let x = vertex[0] - frame % (gridSize * 2)
                let z = vertex[2] - frame * 2 % gridSize + (i % 2 === 0 ? gridSize / 2 : 0)
                let wave = (cos(frame / 45 + x / 50) - sin(frame / 20 + z / 50) + sin(frame / 30 + z * x / 10000))
                let y = vertex[1] + wave * waveSize
                let a = Math.max(0, 1 - (Math.sqrt(x ** 2 + z ** 2)) / depth)
                let tx, ty, tz

                y -= oceanHeight

                // Transformation variables
                tx = x
                ty = y
                tz = z

                // Rotation Y
                tx = x * cos(rad) + z * sin(rad)
                tz = -x * sin(rad) + z * cos(rad)

                x = tx
                y = ty
                z = tz

                // Rotation Z
                tx = x * cos(rad) - y * sin(rad)
                ty = x * sin(rad) + y * cos(rad)

                x = tx;
                y = ty;
                z = tz;

                // Rotation X

                ty = y * cos(rad2) - z * sin(rad2)
                tz = y * sin(rad2) + z * cos(rad2)

                x = tx;
                y = ty;
                z = tz;

                x /= z / perspective
                y /= z / perspective



                if (a < 0.01) return
                if (z < 0) return


                c.globalAlpha = a
                c.fillStyle = `hsl(${180 + wave * 20}deg, 100%, 50%)`
                c.fillRect(x - a * vertexSize / 2, y - a * vertexSize / 2, a * vertexSize, a * vertexSize)
                c.globalAlpha = 1
            })
            c.restore()

            // Post-processing
            postctx.drawImage(canvas, 0, 0)

            postctx.globalCompositeOperation = "screen"
            postctx.filter = 'blur(16px)'
            postctx.drawImage(canvas, 0, 0)
            postctx.filter = 'blur(0)'
            postctx.globalCompositeOperation = "source-over"

            requestAnimationFrame(loop)
        }

        // Generating dots
        for (let i = 0; i < vertexCount; i++) {
            let x = i % oceanWidth
            let y = 0
            let z = i / oceanWidth >> 0
            let offset = oceanWidth / 2
            vertices.push([(-offset + x) * gridSize, y * gridSize, z * gridSize])
        }

        loop()
    </script>

    <style>
        body {
            font: 400 1em/1.5 "Neuton";
            background: #090d00;
            color: rgba(255, 255, 255, 0.25);
            text-align: center;
            margin: 0;
        }

        p.logo {
            text-transform: uppercase;
            letter-spacing: 0.5em;
            display: inline-block;
            border: 4px double rgba(255, 255, 255, 0.25);
            border-width: 4px 0;
            padding: 1.5em 0em;
            position: absolute;
            top: 18%;
            left: 50%;
            width: 40em;
            margin: 0 0 0 -20em;
        }

        p.logo span {
            font: 700 4em/1 "Oswald", sans-serif;
            letter-spacing: 0;
            padding: 0.25em 0 0.325em;
            display: block;
            margin: 0 auto;
            text-shadow: 0 0 80px rgba(255, 255, 255, 0.5);
            /* Clip Background Image */
            background: url(./animated-text-fill.jpg) repeat-y;
            -webkit-background-clip: text;
            background-clip: text;
            /* Animate Background Image */
            -webkit-text-fill-color: transparent;
            -webkit-animation: aitf 80s linear infinite;
            /* Activate hardware acceleration for smoother animations */
            -webkit-transform: translate3d(0, 0, 0);
            -webkit-backface-visibility: hidden;
        }

        /* Animate Background Image */
        @-webkit-keyframes aitf {
            0% {
                background-position: 0% 50%;
            }

            100% {
                background-position: 100% 50%;
            }
        }

        p.logo {
            position: absolute;
            z-index: 10;
        }
    </style>
    <p class="logo">
        Data Science Leaders
        <span>
            ZILLIZ
        </span>
        &mdash; Redefine data science &mdash;
    </p>

    <p class="copyright">
        <span>沪ICP备12345678号</span>
        <span>沪公网安备 1234567890号</span>
    </p>

    <style>
        .copyright {
            position: absolute;
            z-index: 10;
            color: #00345d;
            bottom: 0;
            text-align: center;
            width: 100%;
        }
    </style>

</body>

</html>